﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Hybrid.Threading.Sync
{
    class Singleton
    {
        //s_lock对象是实现线程安全所需要的.定义这个对象时,我们假设创建单实例对象的
        //代价高于创建一个object对象,并假设可能根本不需要创建单实例对象,
        //否则,更经济,更简单的做法是在一个类构造器中创建单实例对象
        private static object s_lock = new object();
        //这个字段引用一个Singleton对象
        private static Singleton s_value = null;
        //私有构造器阻止这个类外部的任何代码创建实例
        private Singleton()
        {
            //把初始化一个Singleton对象的代码放在这里
        }
        //以下公共静态方法返回Singleton对象(如果必要就创建它)
        public static Singleton GetSingleton()
        {
            //如果对象已经创建,直接返回(这样速度很快)
            if (s_value != null) return s_value;

            Monitor.Enter(s_lock);//还没创建,只让一个线程创建它
           
            if (s_value == null)
            { 
                //仍未创建,创建它
                Singleton temp = new Singleton();
                //将引用保存到s_value中
                Interlocked.Exchange(ref s_value, temp);
            }
            Monitor.Exit(s_lock);
            //返回一个Singleton对象的引用
            return s_value;
        }
        
    }

    class Singleton2
    {
        private static Singleton2 s_value = null;
        //私有构造器阻止这个类外部的任何代码创建实例
        private Singleton2()
        {
            //把初始化一个Singleton对象的代码放在这里
        }
        //以下公共静态方法返回Singleton对象(如果必要就创建它)
        public static Singleton2 GetSingleton()
        {
            //如果对象已经创建,直接返回(这样速度很快)
            if (s_value != null) return s_value;

            //创建一个新的Singleton,并把它固定下来(如果另一个线程还没有固定的话)
            Singleton2 temp = new Singleton2();
            //将引用保存到s_value中
            Interlocked.CompareExchange(ref s_value, temp,null);
          
            //如果这个线程竞争失败,新建的第二个Singleton对象就会被垃圾回收
            return s_value;
        }

    }
}
